﻿// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.

using System.Linq;
using StyleMVVM.Utilities;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;

namespace StyleMVVM.Controls.Input
{
	[TemplatePart(Name = WatermarkTextBlockName, Type = typeof(TextBlock))]
	[TemplateVisualState(GroupName = WatermarkStatesGroupName, Name = WatermarkVisibleStateName)]
	[TemplateVisualState(GroupName = WatermarkStatesGroupName, Name = WatermarkHiddenStateName)]
	public sealed class WatermarkTextBox : TextBox
	{
		#region Consts

		private const string WatermarkStatesGroupName = "WatermarkStates";
		private const string WatermarkVisibleStateName = "WatermarkVisible";
		private const string WatermarkHiddenStateName = "WatermarkHidden";
		private const string WatermarkTextBlockName = "WatermarkTextBlock";

		#endregion

		private TextBlock _watermarkTextBlock;

		#region WatermarkText

		public static DependencyProperty WatermarkTextProperty
		{
			get { return InternalWatermarkTextProperty; }
		}

		/// <summary>
		/// WatermarkText Dependency Property
		/// </summary>
		internal static readonly DependencyProperty InternalWatermarkTextProperty =
			DependencyProperty.Register(
				"WatermarkText",
				typeof(string),
				typeof(WatermarkTextBox),
				new PropertyMetadata("Type something..."));

		/// <summary>
		/// Gets or sets the WatermarkText property. This dependency property 
		/// indicates the watermark text to show to the user.
		/// </summary>
		public string WatermarkText
		{
			get { return (string)GetValue(InternalWatermarkTextProperty); }
			set { SetValue(InternalWatermarkTextProperty, value); }
		}

		#endregion

		#region WatermarkStyle

		public static DependencyProperty WatermarkStyleProperty
		{
			get { return InternalWatermarkTextProperty; }
		}

		/// <summary>
		/// WatermarkStyle Dependency Property
		/// </summary>
		internal static readonly DependencyProperty InternalWatermarkStyleProperty =
			DependencyProperty.Register(
				"WatermarkStyle",
				typeof(Style),
				typeof(WatermarkTextBox),
				new PropertyMetadata(null));

		/// <summary>
		/// Gets or sets the WatermarkStyle property. This dependency property 
		/// indicates the style of the watermark (TextBlock).
		/// </summary>
		public Style WatermarkStyle
		{
			get { return (Style)GetValue(InternalWatermarkStyleProperty); }
			set { SetValue(InternalWatermarkStyleProperty, value); }
		}

		#endregion

		public WatermarkTextBox()
		{
			DefaultStyleKey = typeof(WatermarkTextBox);
			this.TextChanged += OnTextChanged;
		}

		protected override void OnApplyTemplate()
		{
			base.OnApplyTemplate();
			_watermarkTextBlock = GetTemplateChild(WatermarkTextBlockName) as TextBlock;
			UpdateWatermarkVisualState();
		}

		private void UpdateWatermarkVisualState()
		{
			var focusedElement = FocusManager.GetFocusedElement() as DependencyObject;
			var isFocused =
				(this == focusedElement) ||
				(focusedElement != null && focusedElement.GetAncestors().Contains(this));
			UpdateWatermarkVisualState(isFocused);
		}

		private void UpdateWatermarkVisualState(bool isFocused)
		{
			if (!isFocused && string.IsNullOrEmpty(this.Text))
			{
				VisualStateManager.GoToState(this, WatermarkVisibleStateName, true);
			}
			else
			{
				VisualStateManager.GoToState(this, WatermarkHiddenStateName, true);
			}
		}

		protected override void OnGotFocus(RoutedEventArgs e)
		{
			base.OnGotFocus(e);
			UpdateWatermarkVisualState(true);
		}

		protected override void OnLostFocus(RoutedEventArgs e)
		{
			base.OnLostFocus(e);
			UpdateWatermarkVisualState(false);
		}

		private void OnTextChanged(object sender, TextChangedEventArgs e)
		{
			UpdateWatermarkVisualState();
		}
	}
}